﻿Function Get-SvnClient
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password
	)
     Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-Debug "Start Get-SvnClient"
    }
    End
    {
        write-Debug "End Get-SvnClient"
        $watch.Stop();
        Write-Debug "Function duration : $($watch.Elapsed)"
    }
    Process
    {
        $svnClient = new-object SharpSvn.SvnClient 

        $svnClient.Authentication.add_SslServerTrustHandlers({
                $_.AcceptedFailures = $_.Failures
                $_.Save = $True
            })


        if ((![String]::IsNullOrEmpty($UserName)) -and (![String]::IsNullOrEmpty($Password)))
        {            
            Write-Debug "Use Basic Authentication to access to svn for User Name : $UserName"
            $svnClient.Authentication.DefaultCredentials = New-Object System.Net.NetworkCredential($UserName,$Password)
        }

        
        $svnClient

    }
}


Function Test-SvnWorkspacePath
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
		[System.String]
		$Path
    )
    Begin
    {
        $svnClient = Get-SvnClient
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
    }
    Process
    {
        if (-not (Test-Path -Path $Path))
        {
            return New-Object System.IO.DirectoryNotFoundException $Path
        }

        
        if (!$svnClient.GetUriFromWorkingCopy($Path))
        {
            return New-Object SharpSvn.SvnException "$Path is not a working copy"
        }
            
    }
}


Function Get-ManagedComment
{
	param
	(
		[parameter(Mandatory = $false)]
		[System.String]
		$Comment,

		[parameter(Mandatory = $true)]
		[System.String]
		$CommandToExecute

    )
    Process
    {
        $computer = Get-ChildItem Env:\COMPUTERNAME
        $user = [System.Security.Principal.WindowsIdentity]::GetCurrent()  
        
        if ($Comment) {$Comment += "`n"}
        
        $Comment += $CommandToExecute
        $comment += "`Origin computer : $($Computer.Value)"
        $comment += "`Origin caller   : $($user.Name)"

        $Comment

    }
}


Function Get-SvnWorkspaceInfo
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password
	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Get-SvnWorkspaceInfo for $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Get-SvnWorkspaceInfo for $Path"
        $watch.Stop();
        Write-Verbose "Function duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Get-SvnWorkspaceInfo -Path $Path"

        $resultAction.Exception = Test-SvnWorkspacePath -Path $Path

        if ($resultAction.Exception)
        {            
            return $resultAction
        }

        $svnInfoArgs = New-Object  SharpSvn.SvnInfoArgs -Property @{
            #ChangeLists=
            #Revision                 
            Depth=[SharpSvn.SvnDepth]::Infinity
            RetrieveActualOnly=$true
            RetrieveExcluded=$true
            #CommandType=[SharpSvn.SvnCommandType]::Info
            #IsLastInvocationCanceled
            #Warnings
            #LastException             
            ThrowOnCancel=$True
            ThrowOnWarning=$False
            ThrowOnError=$True                                                
                                                        }
        
        $result=$null
        if ($svnClient.GetInfo($Path, $svnInfoArgs, [ref] $result))
        {
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction

    }
}


Function Get-SvnWorkspaceStatus
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
        [ValidateScript({(Test-Path $_ -PathType Container) -or (Test-Path $_ -PathType Leaf)})] 
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password,

		[parameter(Mandatory = $false)]
	    [Switch]
		$IncludeRemoteStatus

	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Get-SvnWorkspaceStatus for $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Get-SvnWorkspaceStatus for $Path"
        $watch.Stop();
        Write-Verbose "Functions duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Get-SvnWorkspaceStatus -Path $Path"

        $resultAction.Exception = Test-SvnWorkspacePath -Path $Path

        if ($resultAction.Exception)
        {            
            return $resultAction
        }

        $SvnStatusArgs = New-Object  SharpSvn.SvnStatusArgs -Property @{
                                                        Depth = [SharpSvn.SvnDepth]::Infinity
                                                        RetrieveRemoteStatus = $IncludeRemoteStatus
                                                        RetrieveAllEntries = $true
                                                        }


        $result=$null
        try
        {
            $svnClient.GetStatus($Path, $SvnStatusArgs, [ref] $result) | Out-Null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true

            $SvnStatusResult = New-Object PSObject

            $SvnStatusResult | add-member -MemberType NoteProperty -Name LocalSvnStatus -Value ($result | Group-Object LocalContentStatus)
            $SvnStatusResult | Add-Member -MemberType ScriptProperty -Name HasLocalChange -Value {
                $group = $this.LocalSvnStatus | ? {($_.Name -ne 'Normal') -and ($_.Name -ne 'NotVersioned') -and ($_.Name -ne 'None')}
                ($group.Count -gt 0)
            }

            $SvnStatusResult | Add-Member -MemberType ScriptProperty -Name HasUnversioned -Value {
                $group = $this.LocalSvnStatus | ? {$_.Name -eq 'NotVersioned'}
                ($group.Count -gt 0)
            }


            if ($IncludeRemoteStatus)
            {
                $SvnStatusResult | add-member -MemberType NoteProperty -Name RemoteSvnStatus -Value ($result | Group-Object RemoteContentStatus)
                $SvnStatusResult | Add-Member -MemberType ScriptProperty -Name HasRemoteChange -Value {
                    $group = $this.RemoteSvnStatus | ? {$_.Name -ne 'None'}
                    ($group.Count -gt 0)
                }
            }


            $resultAction | Add-Member -MemberType NoteProperty -Name SvnResult -Value $SvnStatusResult

        }
        catch [Exception]
        {
            $resultAction.Exception = $SvnStatusArgs.LastException
        }

        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction
    }
}


Function Clear-SvnWorkspace
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
        [ValidateScript({(Test-Path $_ -PathType Container) -or (Test-Path $_ -PathType Leaf)})] 
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password
	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Clear-SvnWorkspace for $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Clear-SvnWorkspace for $Path"
        $watch.Stop();
        Write-Verbose "Functions duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Clear-SvnWorkspace -Path $Path"

        $resultAction.Exception = Test-SvnWorkspacePath -Path $Path

        if ($resultAction.Exception)
        {            
            return $resultAction
        }


        $SvnCleanupArgs = New-Object  SharpSvn.SvnCleanupArgs -Property @{
        #CommandType=[SharpSvn.SvnCommandType]::CleanUp
        #IsLastInvocationCanceled= $false
        #Warnings=$null 
        #LastException=$null          
        ThrowOnCancel=$True
        ThrowOnWarning=$False
        ThrowOnError=$True                                                
        }

        $result=$null
        try
        {
            $svnClient.CleanUp($Path,$SvnCleanupArgs) | Out-Null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        catch [Exception]
        {
            $resultAction.Exception = $svnCommitArgs.LastException
        }

        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction

    }
}


Function Restore-SvnWorkspace
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
        [ValidateScript({(Test-Path $_ -PathType Container) -or (Test-Path $_ -PathType Leaf)})] 
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password
	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Restore-SvnWorkspace for $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Restore-SvnWorkspace for $Path"
        $watch.Stop();
        Write-Verbose "Functions duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Restore-SvnWorkspace -Path $Path"

        $resultAction.Exception = Test-SvnWorkspacePath -Path $Path

        if ($resultAction.Exception)
        {            
            return $resultAction
        }


        $SvnRevertArgs = New-Object SharpSvn.SvnRevertArgs -Property @{
            #CommandType=[SharpSvn.SvnCommandType]::Revert
            #IsLastInvocationCanceled= $false
            #Warnings=$null 
            #LastException=$null          
            ThrowOnCancel=$True
            ThrowOnWarning=$False
            ThrowOnError=$True                                                
            Depth=[SharpSvn.SvnDepth]::Infinity
        }


        $result=$null
        try
        {
            $svnClient.Revert($Path, $SvnRevertArgs) | out-null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        catch [Exception]
        {
            $resultAction.Exception = $svnCommitArgs.LastException
        }

        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction


    }
}

Function Get-SvnWorkspace
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
		[System.String]
		$Path,

		[parameter(Mandatory = $true)]
		[System.Uri]
		$Uri,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password,

		[parameter(Mandatory = $false)]
		[System.Uint32]
		$Revision,

		[parameter(Mandatory = $false)]
		[Switch]
		$Switch
	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Get-SvnWorkspace for $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Get-SvnWorkspace for $Path"
        $watch.Stop();
        Write-Verbose "Functions duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Get-SvnWorkspace -Path $Path"

        #Check if the Path is already mapped to a svn repository
        $currentSvnUri = $svnClient.GetUriFromWorkingCopy($Path)
        if ($currentSvnUri)
        {
            if ($currentSvnUri.AbsoluteUri.EndsWith("/") -or $currentSvnUri.AbsoluteUri.EndsWith("\"))
            {
                $currentSvnUri = New-Object System.Uri $currentSvnUri.AbsoluteUri.substring(0, $currentSvnUri.AbsoluteUri.Length -1)
            }
        }


        if ($Uri.AbsoluteUri.EndsWith("/") -or $Uri.AbsoluteUri.EndsWith("\"))
        {
            $Uri = New-Object System.Uri $Uri.AbsoluteUri.substring(0, $Uri.AbsoluteUri.Length -1)
        }


        if ($currentSvnUri -and ($currentSvnUri -ne $Uri))
        {
            #Switch is asked in the command. If there is no pending changes, we can change
            if ($Switch)
            {
                $resultStatus = Get-SvnWorkspaceStatus -Path $Path -UserName $UserName -Password $Password
                if ($resultStatus.LocalSvnStatus.HasChange)
                {
                    $resultAction.Exception = New-Object SharpSvn.SvnException "$Path is already mapped to this uri $currentSvnUri,switch has been asked but pending changes have beein identified"
                }

            }
            else
            {
                $resultAction.Exception = New-Object SharpSvn.SvnException "$Path is already mapped to this uri $currentSvnUri and switch has not been asked"
            }

        }

        if ($resultAction.Exception)
        {            
            return $resultAction
        }



        $svnCheckOutArgs = New-Object SharpSvn.SvnCheckOutArgs -Property @{
            AllowObstructions=$False
            #CommandType=[SharpSvn.SvnCommandType]::Update
            #Revision                 
            IgnoreExternals=$False
            #IsLastInvocationCanceled
            #Warnings
            #LastException             
            ThrowOnCancel=$True
            ThrowOnWarning=$False
            ThrowOnError=$True                                                
            Depth=[SharpSvn.SvnDepth]::Infinity
        }


        $repoUri = new-object SharpSvn.SvnUriTarget($Uri) 

        $result=$null
        try
        {
            $svnClient.CheckOut($repoUri, $Path, $svnCheckOutArgs, [ref] $result) | Out-Null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        catch [Exception]
        {
            $resultAction.Exception = $svnCommitArgs.LastException
        }

        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction

    }
}


Function Update-SvnWorkspace
{
    [CmdletBinding()]
	param
	(
		[parameter(Mandatory = $true)]
        [ValidateScript({(Test-Path $_ -PathType Container) -or (Test-Path $_ -PathType Leaf)})] 
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password,

		[parameter(Mandatory = $false)]
		[System.Uint32]
		$Revision
	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Update-SvnWorkspace for $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Update-SvnWorkspace for $Path"
        $watch.Stop();
        Write-Verbose "Functions duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Update-SvnWorkspace -Path $Path"

        $resultAction.Exception = Test-SvnWorkspacePath -Path $Path

        if ($resultAction.Exception)
        {            
            return $resultAction
        }


        $svnUpdateArgs = New-Object SharpSvn.SvnUpdateArgs -Property @{
            UpdateParents=$False
            AddsAsModifications=$False
            AllowObstructions=$False
            #CommandType=[SharpSvn.SvnCommandType]::Update
            #Revision                 
            IgnoreExternals=$False
            KeepDepth=$False
            #IsLastInvocationCanceled
            #Warnings
            #LastException             
            ThrowOnCancel=$True
            ThrowOnWarning=$False
            ThrowOnError=$True                                                
            Depth=[SharpSvn.SvnDepth]::Infinity
        }

        $result=$null
        try
        {
            $svnClient.Update($Path, $svnUpdateArgs, [ref] $result) | out-null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        catch [Exception]
        {
            $resultAction.Exception = $svnUpdateArgs.LastException
        }
        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction



    }
}


Function Save-SvnWorkspace
{
    [cmdletbinding(SupportsShouldProcess=$True)]
	param
	(
		[parameter(Mandatory = $true)]
        [ValidateScript({(Test-Path $_ -PathType Container) -or (Test-Path $_ -PathType Leaf)})] 
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Comment,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password

	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Save-SvnWorkspace from $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Save-SvnWorkspace from $Path"
        $watch.Stop();
        Write-Verbose "Function duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "Save-SvnWorkspace -Path $Path"

        $resultAction.Exception = Test-SvnWorkspacePath -Path $Path

        if ($resultAction.Exception)
        {            
            return $resultAction
        }


        #Check if there are local changes 
        $svnLocalStatus = Get-SvnWorkspaceStatus -Path $Path -UserName $UserName -Password $Password
        if (-not $svnLocalStatus.Status){throw $svnLocalStatus.Exception}

        if (-not $svnLocalStatus.SvnResult.HasLocalChange)
        {
            $resultAction.Warning = "No changes detection with path $Path"
            Write-Warning $resultAction.Warning

        }


        if ($svnLocalStatus.SvnResult.HasUnversioned)
        {
            $Warning = "Unversioned items exist in path $Path"
            Write-Warning $Warning
            if ($resultAction.Warning) {$resultAction.Warning += "`n$Warning"} 

        }


        $svnCommitArgs = New-Object SharpSvn.SvnCommitArgs -Property @{
            RunTortoiseHooks=$False
            IncludeDirectoryExternals=$False
            IncludeFileExternals=$False
            KeepChangeLists=$False
            #ChangeLists
            KeepLocks=$False
            #CommandType=[SharpSvn.SvnCommandType]::Commit
            #LogProperties
            LogMessage=(Get-ManagedComment -Comment $Comment -CommandToExecute $resultAction.CommandToExecute)
            #IsLastInvocationCanceled
            #Warnings
            #LastException             
            ThrowOnCancel=$True
            ThrowOnWarning=$False
            ThrowOnError=$True                                                
            Depth=[SharpSvn.SvnDepth]::Infinity
        }

        $result=$null
        try
        {
            $svnClient.Commit($Path, $svnCommitArgs, [ref] $result) | Out-Null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        catch [Exception]
        {
            $resultAction.Exception = $svnCommitArgs.LastException
        }

        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction


<#
        $resultAction = Get-RemoteSvnStatus -Path $LocalPath -UserName $UserName -Password $Password
        if ($resultAction.ExitCode -eq -1)
        {
            throw New-Object System.Exception "Unable to obtain svn status from path $LocalPath with following exception $($resultAction.Exception)"
        }    

        $svnMapFolder = $resultAction.Result

        if (!$svnMapFolder.HasChanges)
        {
            Write-Warning "No changes detection with path $LocalPath"
            Write-Output $resultAction
        }
        else
        {
            $computer = Get-ChildItem Env:\COMPUTERNAME
            $subCommand = "ci"
            $Comment += " Save-SvnChanges from $Path of $($Computer.Value)"

            $SvnCommand = [String]::Format("{0} {1} {2} -m '{3}'", $svnExe, $subCommand, $LocalPath, $Comment)

            $svnStatus = Invoke-SvnCommand -SvnCommand $SvnCommand -UserName $UserName -Password $Password
            Write-Output $svnStatus
        }
#>
        
    }
}


Function Add-ObjectToSvn
{
    [cmdletbinding(SupportsShouldProcess=$True)]
	param
	(
		[parameter(Mandatory = $true)]
		[System.String]
		$Path,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password

	)
     Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Add-ObjectToSvn $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Add-ObjectToSvn $Path"
        $watch.Stop();
        Write-Verbose "Function duration : $($watch.Elapsed)"
    }
    Process
    {
        $svnClient.Add($Path)
    }
}


function Sync-SvnWorkspace
{
    [cmdletbinding(DefaultParameterSetName="none")]
	param
	(
		[parameter(Mandatory = $true)]
        [ValidateScript({Test-Path $_ -PathType Container})] 
        [System.String]
        $Path,

		[parameter(Mandatory = $true)]
        [System.String]
        $Comment,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password
	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start Sync-SvnWorkspace from $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End Sync-SvnWorkspace from $Path"
        $watch.Stop();
        Write-Verbose "Function duration : $($watch.Elapsed)"
    }
    Process
    {
        #Check if there are local changes 
        $svnLocalStatus = Get-SvnWorkspaceStatus -Path $Path -UserName $UserName -Password $Password
        if (-not $svnLocalStatus.Status){throw $svnLocalStatus.Exception}

        if ($svnLocalStatus.SvnResult.HasUnversioned)
        {
            Write-Verbose "Found Unversioned items in $Path, add them to be ready to svn commit"
            $svnLocalStatus.InternalResult | ? {$_.LocalContentStatus -eq 'NotVersioned'} | ForEach-Object {
                Add-ObjectToSvn -Path $_.FullPath -UserName $UserName -Password $Password | Out-Null
            }
        }

        #Commit into SVN
        $svnCommitStatus = Save-SvnWorkspace -Path $Path -Comment $Comment -UserName $UserName -Password $Password

        Write-Output $svnCommitStatus
        
    }

}


function New-SvnRepositoryDirectory
{
    [cmdletbinding(DefaultParameterSetName="none")]
	param
	(
		[parameter(Mandatory = $true)]
        [Uri]
        $ParentDirectory,

        [Parameter(ParameterSetName="ByServer",Mandatory=$true)] 
        [System.String]
        $Name,

		[parameter(Mandatory = $true)]
        [System.String]
        $Comment,

		[parameter(Mandatory = $false)]
	    [System.String]
		$UserName,

		[parameter(Mandatory = $false)]
	    [System.String]
		$Password,

		[parameter(Mandatory = $false)]
	    [Switch]
		$CreateParents

	)
    Begin
    {
        $watch = [system.diagnostics.stopwatch]::StartNew() 
        write-verbose "Start New-SvnRepositoryDirectory from $Path"
        $svnClient = Get-SvnClient -UserName $UserName -Password $Password
    }
    End
    {
        if ($svnClient) {$svnClient.Dispose()}
        write-verbose "End New-SvnRepositoryDirectory from $Path"
        $watch.Stop();
        Write-Verbose "Function duration : $($watch.Elapsed)"
    }
    Process
    {

        $resultAction = New-ResultActionObject
        $resultAction.CommandToExecute = "New-SvnRepositoryDirectory -ParentDirectory $ParentDirectory"


        $svnCreateDirectoryArgs = New-Object SharpSvn.SvnCreateDirectoryArgs -Property @{
            MakeParents=$CreateParents
            CreateParents=$CreateParents
            #CommandType=[SharpSvn.SvnCommandType]::CreateDirectory
            LogMessage=(Get-ManagedComment -Comment $Comment -CommandToExecute $resultAction.CommandToExecute)
            #IsLastInvocationCanceled=$false
            #Warnings
            #LastException
            ThrowOnCancel=$True
            ThrowOnWarning=$False
            ThrowOnError=$True                                                
        }


        $result=$null
        try
        {
            $targetUrl = [System.IO.Path]::Combine($ParentDirectory,$Name).Replace("\","/")
            $svnClient.RemoteCreateDirectory($targetUrl, $svnCreateDirectoryArgs, [ref] $result) | Out-Null
            $resultAction.ExitCode = 0
            $resultAction.Status = $true
        }
        catch [Exception]
        {
            $resultAction.Exception = $svnCreateDirectoryArgs.LastException
        }

        $resultAction.InternalResult = $result
        $resultAction.End = (get-date)
        $resultAction.Duration = $resultAction.End - $resultAction.Start

        $resultAction


    
    }

}

